/*
 * StdGateDescription.java
 * 
 * last update: 16.01.2010 by Stefan Saru
 * 
 * author:	Alec(panovici@elcom.pub.ro)
 * 
 * Obs:
 */


package engine;

import java.util.*;
import java.io.*;
import middle.*;

/**
 * Things all standard gates have
 */
@SuppressWarnings("serial")
abstract class StdGateDescription implements ModuleFactory{

	//n-input gates  
	public static final byte and  = 0;
	public static final byte nand = 1;
	public static final byte or   = 2;
	public static final byte nor  = 3;
	public static final byte xor  = 4;
	public static final byte xnor = 5;
	//n-output gates
	public static final byte buf  = 6;
	public static final byte not  = 7;
	//trstate gates
	public static final byte bufif0 = 8;
	public static final byte bufif1 = 9;
	public static final byte notif0 = 10;
	public static final byte notif1 = 11;

	//cmoses
	public static final byte cmos  = 12;
	public static final byte nmos  = 13;
	public static final byte pmos  = 14;
	public static final byte rcmos = 15;
	public static final byte rnmos = 16;
	public static final byte rpmos = 17;

	//trans
	public static final byte tran     = 18;
	public static final byte rtran    = 19;
	public static final byte tranif0  = 20;
	public static final byte rtranif0 = 21;
	public static final byte tranif1  = 22;
	public static final byte rtranif1 = 23;

	public static final String [] typeToString =
	{
		"and", "nand",
		"or", "nor",
		"xor", "xnor",

		"buf", "not",

		"bufif0", "bufif1",
		"notif0", "notif1",

		"cmos", "nmos", "pmos",
		"rcmos", "rnmos", "rpmos",
		"tran", "rtran",
		"tranif0", "rtranif0",
		"tranif1", "rtranif1"
	};

	static {

		VeriParser.builtinGates.put(typeToString[and],
				new NInputGateDescription(and));
		VeriParser.builtinGates.put(typeToString[nand],
				new NInputGateDescription(nand));
		VeriParser.builtinGates.put(typeToString[or],
				new NInputGateDescription(or));
		VeriParser.builtinGates.put(typeToString[nor],
				new NInputGateDescription(nor));
		VeriParser.builtinGates.put(typeToString[xor],
				new NInputGateDescription(xor));
		VeriParser.builtinGates.put(typeToString[xnor],
				new NInputGateDescription(xnor));

		VeriParser.builtinGates.put(typeToString[buf],
				new NOutputGateDescription(buf));
		VeriParser.builtinGates.put(typeToString[not],
				new NOutputGateDescription(not));

		VeriParser.builtinGates.put(typeToString[bufif0],
				new EnableGateDescription(bufif0));
		VeriParser.builtinGates.put(typeToString[bufif1],
				new EnableGateDescription(bufif1));
		VeriParser.builtinGates.put(typeToString[notif0],
				new EnableGateDescription(notif0));
		VeriParser.builtinGates.put(typeToString[notif1],
				new EnableGateDescription(notif1));

		VeriParser.builtinGates.put(typeToString[cmos],
				new MOSGateDescription(cmos));
		VeriParser.builtinGates.put(typeToString[nmos],
				new MOSGateDescription(nmos));
		VeriParser.builtinGates.put(typeToString[pmos],
				new MOSGateDescription(pmos));
		VeriParser.builtinGates.put(typeToString[rcmos],
				new MOSGateDescription(rcmos));
		VeriParser.builtinGates.put(typeToString[rnmos],
				new MOSGateDescription(rnmos));
		VeriParser.builtinGates.put(typeToString[rpmos],
				new MOSGateDescription(rpmos));

		VeriParser.builtinGates.put(typeToString[tran],
				new TranGateDescription(tran));
		VeriParser.builtinGates.put(typeToString[rtran],
				new TranGateDescription(rtran));
		VeriParser.builtinGates.put(typeToString[tranif0],
				new TranGateDescription(tranif0));
		VeriParser.builtinGates.put(typeToString[rtranif0],
				new TranGateDescription(rtranif0));
		VeriParser.builtinGates.put(typeToString[tranif1],
				new TranGateDescription(tranif1));
		VeriParser.builtinGates.put(typeToString[rtranif1],
				new TranGateDescription(rtranif1));
	}

	Delay3 delay;
	byte type;

	/**
	 * how many delays a spcific gate type can have
	 */
	 int delaySpecs;

	/**
	 * Use this counter to uniquify names for anonymous instances.
	 */
	 int anonymousInstanceNo;

	StdGateDescription (byte type, int delaySpecs) {
		this.type = type;
		delay = Delay3.nullDelay();
		this.delaySpecs = delaySpecs;

		anonymousInstanceNo = 0;
	}

	/**
	 * Return a new unique name for an anonymous instance. The name is made up
	 * from the ty[e's name and a unique number.
	 */
	 public String createNewName () {
		 return typeToString[type] + anonymousInstanceNo ++;
	 }

	 public String name() {
		 return new String(typeToString [type]);
	 }

	 public void setParams(Vector results, Delay3 delays)
	 throws ParseException
	 {
		 if ((results != null) && (delays != null))
			 throw new ParseException(": error: primitive gates cannot" +
			 " have param specs");

		 if(results != null && results.size() > 0){
			 if (results.size() > delaySpecs)
				 throw new ParseException(": error: primitive delay can have only " +
						 delaySpecs + " values");
			 delay = new Delay3();
			 int aux =  (int) ((Result)results.elementAt(0)).getLong();
			 delay.setDelay1(aux, aux, aux);
			 if (results.size() > 1) {
				 aux = (int) ((Result)results.elementAt(1)).getLong();
				 delay.setDelay2(aux, aux, aux);
				 delay.delaySpecs = 2;
				 if (results.size() > 2) {
					 aux = (int) ((Result)results.elementAt(2)).getLong();
					 delay.setDelay3(0, 0, 0);
					 delay.delaySpecs = 3;
				 }
			 }
		 }

		 if (delays != null) {
			 if (delays.delaySpecs > delaySpecs)
				 delay = delays;
		 }

		 xConsole.debug("delay is: " + this.delay);
	 }

	 public void unsetParams() {
		 delay = Delay3.nullDelay();
	 }

	 public boolean isTop() {
		 return false;
	 }

}

